/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* includes (local) ----------------------------------------------------------*/
#include <hal_spi.h>
/* includes (standard library, system) ---------------------------------------*/
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <x_errno.h>

/* defines -------------------------------------------------------------------*/
/* typedefs ------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables (extern) --------------------------------------------------------*/
/* variables (local) ---------------------------------------------------------*/
/* variables (global) --------------------------------------------------------*/
/* inlines -------------------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/

hal_spi_t *hal_spi_open(const char *name)
{
    return container_of(hal_open(name, 0), hal_spi_t, parent);
}

int hal_spi_write(hal_spi_t *spi, const void *buf, size_t len, uint32_t timeout)
{
    int ret;

    if (spi == NULL || buf == NULL) {
        return -EINVAL;
    }
    if (spi->methods->write == NULL) {
        return -ENOSYS;
    }
    if (unlikely(k_mutex_lock(&spi->lock) != 0)) {
        return -1;
    }
    ret = spi->methods->write(spi, buf, len, timeout);
    k_mutex_unlock(&spi->lock);

    return ret;
}

int hal_spi_read(hal_spi_t *spi, void *buf, size_t len, uint32_t timeout)
{
    int ret;

    if (spi == NULL || buf == NULL) {
        return -EINVAL;
    }
    if (spi->methods->read == NULL) {
        return -ENOSYS;
    }
    if (unlikely(k_mutex_lock(&spi->lock) != 0)) {
        return -1;
    }
    ret = spi->methods->read(spi, buf, len, timeout);
    k_mutex_unlock(&spi->lock);

    return ret;
}

int hal_spi_write_read(hal_spi_t *spi, const void *txbuf, void *rxbuf, size_t len, uint32_t timeout)
{
    int ret;

    if (spi == NULL || txbuf == NULL || rxbuf == NULL) {
        return -EINVAL;
    }
    if (spi->methods->write_read == NULL) {
        return -ENOSYS;
    }
    if (unlikely(k_mutex_lock(&spi->lock) != 0)) {
        return -1;
    }
    ret = spi->methods->write_read(spi, txbuf, rxbuf, len, timeout);
    k_mutex_unlock(&spi->lock);

    return ret;
}

int hal_spi_ioctl(hal_spi_t *spi, int cmd, ...)
{
    int ret = 0;
    va_list valist;

    if (spi == NULL) {
        return -EINVAL;
    }
    if (spi->methods->ioctl == NULL) {
        return -ENOSYS;
    }
    if (unlikely(k_mutex_lock(&spi->lock) != 0)) {
        return -EAGAIN;
    }

    va_start(valist, cmd);
    ret = spi->methods->ioctl(spi, cmd, valist);
    va_end(valist);

    k_mutex_unlock(&spi->lock);

    return ret;
}

int hal_spi_register(hal_spi_t *spi, const char *name, const hal_spi_methods_t *methods,
                     uintptr_t data)
{
    int ret = 0;

    if (spi == NULL || name == NULL || methods == NULL) {
        return -EINVAL;
    }

    spi->parent.name = name;
    spi->methods = methods;
    spi->mode = (uint8_t)data;

    if (unlikely(k_mutex_init(&spi->lock) != 0)) {
        return -ENOMEM;
    }

    if ((ret = hal_register(&spi->parent)) != 0) {
        return ret;
    }

    return ret;
}
